package com.cskaoyan.config;

import com.cskaoyan.shiro.CustomAuthenticator;
import com.cskaoyan.shiro.CustomRealm;
import com.cskaoyan.shiro.UserRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 类<code>Doc</code>用于：TODO
 *
 * @author Acher
 * @version 1.0
 * @date 2021-10-20
 */
@Configuration
@EnableConfigurationProperties(AnonProperties.class)
public class ShiroConfig {

    AnonProperties anonProperties;

    public ShiroConfig(AnonProperties anonProperties) {
        this.anonProperties = anonProperties;
    }

    // 默认认证器和授权器的管理器
    @Bean
    public DefaultWebSecurityManager securityManager(CustomRealm customRealm,UserRealm userRealm,
            DefaultWebSessionManager sessionManager, CustomAuthenticator customAuthenticator) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //默认的认证器ModularRealmAuthenticator和默认的授权器ModularRealmAuthorizer
        //realm(s) → 自定义的Realm
//        securityManager.setRealm(realm);
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(customRealm);
        realms.add(userRealm);
        securityManager.setRealms(realms);
        //如果要写自定义的认证器和授权器
        //→ 继承默认的认证器和授权器 → 也可以实现Authenticator、Authorizer接口
        securityManager.setSessionManager(sessionManager);
        securityManager.setAuthenticator(customAuthenticator);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        //认证失败 → 重定向的请求url → 默认值login.jsp
        shiroFilter.setLoginUrl("/");
        //使用里面的Filter的时候，需要使用到SecurityManager
        shiroFilter.setSecurityManager(securityManager);
        // key 请求url
        // value filter -> anon（匿名）、autoc（认证）、perms（授权）
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        List<String> anons = anonProperties.getAnon();
        for (String anon : anons) {
            filterChainDefinitionMap.put(anon,"anon");
        }
        filterChainDefinitionMap.put("/**", "authc");// 拦截所有请求并认证
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }

    // advisor
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public CustomAuthenticator authenticator(CustomRealm customRealm, UserRealm userRealm){
        CustomAuthenticator customAuthenticator = new CustomAuthenticator();
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(customRealm);
        realms.add(userRealm);
        customAuthenticator.setRealms(realms);
        return customAuthenticator;
    }

}
